﻿using System;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using LumiSoft.Net.Media;
using LumiSoft.Net.SIP.Message;
using TEL.ClientClasses.Private;
using TEL.ClientClasses.Public;
using TEL.ClientClasses.SipInterfaces;
using TEL.WinMediaWPF.Audio;

namespace TEL.ClientClasses
{
    public class SipVizard
    {
        public StringFromString DisplayNameByPhone = null;

        private SipOperation _operation = null;

        public SipOperation Operation
        {
            get { return _operation; }
            set
            {
                _operation = value;
                if (_operation != null)
                {
                    _operation.RegisteringEvent += new EventHandler<RegistrationEventArgs>(Operation_RegisteringEvent);
                    _operation.SipLinesCreateEvent += new EventHandler<SipLinesEventArgs>(Operation_SipLinesCreateEvent);
                    _operation.AnswerSaveStarting += new EventHandler<StringEventArgs>(Operation_AnswerSaveStarting);
                    Operation.DND = _phoneOption.dnd;
                }
            }
        }

        private IInfoPanel m_infoPanel = null;
        public IInfoPanel InfoPanel
        {
            get { return m_infoPanel; }
            set
            {
                m_infoPanel = value;
                m_infoPanel.ContactCall += new EventHandler<StringEventArgs>(m_infoPanel_ContactCall);
                m_infoPanel.MicrophoneChecked += new EventHandler<BoolEventArgs>(m_infoPanel_MicrophoneChecked);
            }
        }

        void m_infoPanel_MicrophoneChecked(object sender, BoolEventArgs e)
        {
            if (Operation != null) Operation.SetMicroPhobeActive(e.Message);
        }

        void m_infoPanel_ContactCall(object sender, StringEventArgs e)
        {
            if (LineManager.ActiveLine != null && LineManager.ActiveLine.State == CallState.DialTone)
            {
                LineManager.ActiveLine.ClearNumberCall();
                BtnPanel.EnterNumber(e.Message);
                PhoneOption.AutoAcceptMainClick();
            }
        }

        public void ClearNumber()
        {
            if (LineManager.ActiveLine != null && LineManager.ActiveLine.State == CallState.DialTone)
            {
                LineManager.ActiveLine.ClearNumberCall();
            }
        }

        private int _lineEmployedCount = 0;
        public int LineEmployedCount
        {
            get { return _lineEmployedCount; }
            set
            {
                _lineEmployedCount = value;
                PhoneOption.SetSaveEnable(_lineEmployedCount > 0);
            }
        }

        private IBtnPannel _btnPanel = null;
        public IBtnPannel BtnPanel
        {
            get { return _btnPanel; }
            set
            {
                if (value != null)
                {
                    _btnPanel = value;
                    _btnPanel.NumberEvent += new EventHandler<ClickNumberEventArgs>(_btnPanel_NumberEvent);
                }
            }
        }

        private IPhoneOption _phoneOption = null;
        public IPhoneOption PhoneOption
        {
            get { return _phoneOption; }
            set
            {
                _phoneOption = value;
                _phoneOption.DNDChanged += new EventHandler<BoolEventArgs>(_phoneOption_DNDChanged);
                _phoneOption.SavingChanged += new EventHandler<BoolEventArgs>(_phoneOption_SavingChanged);
                _phoneOption.ConfChanged += new EventHandler<BoolEventArgs>(_phoneOption_ConfChanged);
                _phoneOption.MainClickEvent += new EventHandler(_phoneOption_MainClickEvent);
                _phoneOption.XferClick += new EventHandler(_phoneOption_XferClick);
                _phoneOption.ClearEvent += new EventHandler(_phoneOption_ClearEvent);
                _phoneOption.TransferClick += new EventHandler(_phoneOption_TransferClick);
            }
        }

        void _phoneOption_XferClick(object sender, EventArgs e)
        {
            try
            {
                if (!PhoneOption.Xfer)
                {
                    if (LineManager.ActiveLine == null) throw new ArgumentNullException("SipLine");

                    if (LineManager.ActiveLine.State == CallState.Active)
                        LineManager.XferLine = LineManager.ActiveLine;
                }
                else
                {
                    if (LineManager.XferLine == null) throw new ArgumentNullException("SipLine");
                    if (LineManager.ActiveLine.State == CallState.Active)
                    {
                        LineManager.XferLine.Xfer(LineManager.ActiveLine);
                        LineManager.XferLine = null;
                    }
                    else
                    {
                        LineManager.ActiveLine = LineManager.XferLine;
                        LineManager.XferLine = null;
                    }
                    
                }
            }

            catch (Exception)
            {
            }
        }

        void _phoneOption_TransferClick(object sender, EventArgs e)
        {
            try
            {
                if (!PhoneOption.Transfer)
                {
                    if (LineManager.ActiveLine == null) throw new ArgumentNullException("SipLine");

                    if (LineManager.ActiveLine.State == CallState.Active)
                        LineManager.TransferLine = LineManager.ActiveLine;
                }
                else
                {
                    if (LineManager.TransferLine == null) throw new ArgumentNullException("SipLine");

                    LineManager.ActiveLine = LineManager.TransferLine;
                    LineManager.TransferLine = null;
                }
            }

            catch (Exception)
            {
            }
        }

        void _phoneOption_ClearEvent(object sender, EventArgs e)
        {
            try
            {
                if (LineManager.ActiveLine == null || !LineManager.ActiveLine.IsHasCall)
                {
                    LineManager.ActiveLine.RemoveLastNum();
                }
            }
            catch (Exception)
            {
            }
        }

        void _phoneOption_MainClickEvent(object sender, EventArgs e)
        {
            try
            {
                if (InfoPanel == null)
                    throw new ArgumentNullException("InfoPanel is null");
                if (Operation == null)
                    throw new ArgumentNullException("Operation is null");
                if (LineManager == null)
                    throw new ArgumentNullException("LineManager is null");

                if (LineManager.ActiveLine == null) return;
                
                LineManager.ActiveLine.StopPlayer();

                if(PhoneOption.Transfer)
                {
                    LineManager.TransferLine.Transfer(LineManager.ActiveLine);
                    if (LineManager.ActiveLine.State == CallState.DialTone) LineManager.ActiveLine.ToggleCallOnHold();
                    else  LineManager.ActiveLine.CallTerminated();
                    return;
                }

                if (!LineManager.ActiveLine.IsHasCall)
                {
                    if (!string.IsNullOrEmpty(LineManager.ActiveLine.NumEnterText))
                    {
                        if (!PhoneOption.Conf) LineManager.ToHoldAll(CallState.Active);
                        LineManager.ActiveLine.Calling();
                        LineManager.ActiveLine.ClearNumberCall();
                        return;
                    }
                }
                else
                {
                    LineManager.ActiveLine.ClearNumberCall();
                    if (LineManager.ActiveLine.State == CallState.WaitingToAccept)
                    {
                        if (!PhoneOption.Conf) LineManager.ToHoldAll(CallState.Active);
                       // Operation.AcceptCall(LineManager.ActiveLine);
                        LineManager.ActiveLine.AcceptCall();
                    }
                    else
                    {
                        if (LineManager.ActiveLine.State == CallState.Hold)
                        {
                            LineManager.ActiveLine.ToggleCallOnHold();
                        }
                        LineManager.ActiveLine.CallTerminated();

                        InfoPanel.ClearTempContact();
                    }
                }
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard UpCall", error, false));
            }
        }

        void _phoneOption_ConfChanged(object sender, BoolEventArgs e)
        {
            try
            {
                Operation.SetConference(e.Message);
                if (!e.Message)
                {
                    Operation.TrminateAfterConfirence();
                }
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard ConfChanged", error, false));
            }
        }

        void _phoneOption_SavingChanged(object sender, BoolEventArgs e)
        {
            if (Operation != null && InfoPanel != null)
                try
                {
                    if (e.Message) LineManager.ActiveLine.StartWavSaving();
                    else LineManager.ActiveLine.StoptWavSaving(false);
                }
                catch (Exception error)
                {
                    if (ErrorEvent != null)
                        ErrorEvent(this, new StrErrorEventArgs("SavingChanged", error, false));
                }
        }

        void _phoneOption_DNDChanged(object sender, BoolEventArgs e)
        {
            if (Operation != null)
                try
                {
                    Operation.DND = e.Message;
                }
                catch (Exception error)
                {
                    if (ErrorEvent != null)
                        ErrorEvent(this, new StrErrorEventArgs("SavingChanged", error, false));
                }
        }

        private ILineManager _linemanager = null;
        public ILineManager LineManager
        {
            get { return _linemanager; }
            set
            {
                _linemanager = value;
                _linemanager.ActiveLineChange += new EventHandler<SipLineEventArgs>(_linemanager_ActiveLineChange);
                _linemanager.TransferLineChange += new EventHandler<SipLineEventArgs>(_linemanager_TransferLineChange);
                _linemanager.XferLineChange += new EventHandler<SipLineEventArgs>(_linemanager_XferLineChange);
            }
        }

        void _linemanager_XferLineChange(object sender, SipLineEventArgs e)
        {
            PhoneOption.Xfer = e.Line != null;
        }

        void _linemanager_TransferLineChange(object sender, SipLineEventArgs e)
        {
            PhoneOption.Transfer = e.Line != null;
        }

        void Operation_SipLinesCreateEvent(object sender, SipLinesEventArgs e)
        {
            try
            {
                if (LineManager == null)
                    throw new NullReferenceException("LineManager is null");
                e.Lines.ForEach(x =>{
                                        x.CallChanged += new EventHandler<CallEventArgs>(x_CallChanged);
                                        x.LineStateChanged += new EventHandler<CallEventArgs>(x_LineStateChanged);
                                        x.NumEnterTextChanged += new EventHandler<ReferEventArgs>(x_NumEnterTextChanged);
                                    });
                LineManager.CreateSipLines(e.Lines);
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard SipLinesCreateEvent", error, false));
            }
        }

        public event EventHandler<StringEventArgs> AutoRadialEvent;
        void x_NumEnterTextChanged(object sender, ReferEventArgs e)
        {
            InfoPanel.SetEnterText(e.LineCallDestination);
            CallToDisplay();
            if (NumEnterTextChanged != null) NumEnterTextChanged(this, e);
        }

        void x_LineStateChanged(object sender, CallEventArgs e)
        {
            try
            {
               
                SipLine sipLine = sender as SipLine;
                if (sipLine != null)
                {
                     Operation.SimpleLog.Write(LogType.Info,"Новое состояние линии", sipLine.State.ToString());
                    if (sipLine.State == CallState.Entity)
                    {
                        _phoneOption_ClearEvent(this, null);
                    }

                    if (sipLine.State == CallState.Active && !sipLine.IsFocus && sipLine.KillLineNotDialog == 1)
                        sipLine.ToggleCallOnHold();
                    if (sipLine.State == CallState.WaitingToAccept && PhoneOption.AutoAccept)
                        Task.Factory.StartNew(() => StarttingAutoAccept());

                    if(sipLine.State == CallState.Disposed && PhoneOption.AutoRedial)
                    {
                       string autoNumber = GetNumberFromSip(sipLine.LineCall);
                        sipLine.CallTerminated();
                        InfoPanel.SetEnterText("Пвторный набор");
                        Thread.Sleep(5000);
                        if (PhoneOption.AutoRedial)
                        {
                            if (AutoRadialEvent != null)
                                AutoRadialEvent.BeginInvoke(this, new StringEventArgs(autoNumber), null, null);
                        }
                        else
                        {
                            InfoPanel.SetEnterText(string.Empty);
                        }
                    }
                }
            }
            catch (Exception)
            {

            }
            if (CallLineEvent != null) CallLineEvent(sender, e);
        }

        private void CallToDisplay()
        {
            if (LineManager.ActiveLine == null)
            {
                InfoPanel.SetLineCall(string.Empty, string.Empty);
                return;
            }
            if (LineManager.ActiveLine.State == CallState.Entity)
            {
                InfoPanel.SetLineCall(string.Empty, string.Empty);
                return;
            }

            if (LineManager.ActiveLine.IsHasCall)
            {
                string displayName = LineManager.ActiveLine.DisplayName;
                if (string.IsNullOrEmpty(displayName))
                    displayName = DisplayNameByPhone == null
                                      ? string.Empty
                                      : DisplayNameByPhone(GetNumberFromSip(LineManager.ActiveLine.LineCall));

                InfoPanel.SetLineCall(LineManager.ActiveLine.LineCall, displayName);
            }
        }

        void x_CallChanged(object sender, CallEventArgs e)
        {
            try
            {
                SipLine sipLine = sender as SipLine;
                if (sipLine == null) throw new ArgumentNullException("SipLine is null");
                SipLine sl = !sipLine.IsHasCall ? null : sipLine;
                if(sl != null) LineManager.ActiveLine = sl;
                
                CallToDisplay();
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard SipVizard_LineEvent", error, false));
            }
        }
     
        void _linemanager_ActiveLineChange(object sender, SipLineEventArgs e)
        {
            try
            {
                Operation.SetFocusToLines(e.Line);
                if (e.Line != null)
                {
                    CallToDisplay();
                }
                else
                {
                    InfoPanel.SetLineCall(string.Empty, string.Empty);
                }
            }
            catch (Exception)
            {
            }
        }

        void _btnPanel_NumberEvent(object sender, ClickNumberEventArgs e)
        {
            try
            {
                if (InfoPanel == null) throw new ArgumentNullException("InfoPanel is null");
                if (Operation == null) throw new ArgumentNullException("Operation is null");
                if (LineManager == null) throw new ArgumentNullException("LineManager is null");


                if (LineManager.ActiveLine != null && LineManager.ActiveLine.State == CallState.DialTone)
                {
                    LineManager.ActiveLine.StopPlayer();
                }
                else
                {
                    SipLine sipLine = Operation.GetLineFree();
                    LineManager.ActiveLine = sipLine;
                    sipLine.StopPlayer();
                }

                if (LineManager.ActiveLine != null)
                {
                    LineManager.ActiveLine.AddNumber(e.NumberCaption.ToString(), e.RegexStr);
                    Operation.AddToneDTMF(LineManager.ActiveLine, e);
                }
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard NumberEvent", error, false));
            }
        }

        void Operation_AnswerSaveStarting(object sender, StringEventArgs e)
        {
            try
            {
                PhoneOption.Saving = true;
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard AnswerSaveStarting", error, false));
            }
        }

       public event EventHandler<RegistrationEventArgs> RegisteringEvent;
       public event EventHandler<CallEventArgs> CallLineEvent;
       public event EventHandler<StrErrorEventArgs> ErrorEvent;
       public event EventHandler<ReferEventArgs> NumEnterTextChanged;

        public RegistrationState Registration{get; private set; }

        void Operation_RegisteringEvent(object sender, RegistrationEventArgs e)
        {
            try
            {
                if (InfoPanel == null) throw new ArgumentNullException("InfoPanel is null");
                if (Operation == null) throw new ArgumentNullException("Operation is null");
                if (BtnPanel == null) throw new ArgumentNullException("BtnPanel is null");

                Registration = e.State;
                InfoPanel.SetRegistrationData(e.Message);
                BtnPanel.SetEnabled(e.State == RegistrationState.Registered);
                if ((e.State != RegistrationState.Registered))
                {  Operation.KillCallAll();}
                if (RegisteringEvent != null) RegisteringEvent(this, e);
            }
            catch (Exception error)
            {
                if (ErrorEvent != null)
                    ErrorEvent(this, new StrErrorEventArgs("SipVizard RegisteringEvent", error, false));
            }

        }

       #region AnswerSave

        private IAnsweringMachine _answeringMachine = null;
        public IAnsweringMachine AnsweringMachine
        {
            get { return _answeringMachine; }
            set
            {
                _answeringMachine = value;
                if (_answeringMachine != null)
                    _answeringMachine.AnswerSaveEvent += new EventHandler<BoolEventArgs>(_answeringMachine_AnswerSaveEvent);
            }
        }

        private AnswerMashiceContent Answer = null;

        void _answeringMachine_AnswerSaveEvent(object sender, BoolEventArgs e)
        {
            try
            {
                if (e.Message)
                {
                    if (Answer != null) Answer = null;
                    Answer = new AnswerMashiceContent(new AudioIn(SipOperation.AudioInStream, 8000, 16, 1));
                }
                else
                {
                    Answer.Dispose();
                    Answer = null;
                }
            }
            catch (Exception)
            {
            }
        }

        #endregion

        private void StarttingAutoAccept()
        {
            TimeSpan timeSpan = DateTime.Now.AddSeconds(5) - DateTime.Now;
            System.Threading.Thread.Sleep(timeSpan);

            if (PhoneOption == null) return;
            if(LineManager == null) return;
            SipLine sipLine = LineManager.ActiveLine;
            if(sipLine == null || !sipLine.IsHasCall) return;
            if(sipLine.State == CallState.WaitingToAccept)
                PhoneOption.AutoAcceptMainClick();

        }
        public static string GetNumberFromSip(string sipUri)
        {
            try
            {
                string f = Regex.Replace(sipUri, "sip:", "", RegexOptions.IgnoreCase).Trim();
                f = Regex.Match(f, "^(?<num>.*?)@").Groups["num"].Value.Trim();
                return string.IsNullOrEmpty(f) ? "nan" : f;
            }
            catch (Exception error)
            {
                return string.Empty;
            }

        }
    }
}